function [thrs, fars, frrs] = slverifyroc(scores, rlabels, qlabels, op, npts)
%SLVERIFYROC Computes the verification ROC
%
% [ Syntax ]
%   - [thrs, fars, frrs] = slverifyroc(scores, rlabels, qlabels, op)
%   - [thrs, fars, frrs] = slverifyroc(scores, rlabels, qlabels, op, npts)
% 
% [ Arguments ]
%   - scores:       the score matrix for verification
%   - rlabels:      the labels of references
%   - qlabels:      the labels of queries
%   - op:           the option of thresholding
%                   \{:
%                      - high:  accepts if score >= threshold
%                      - low:   accepts if score < threshold
%                   \:}
%   - npts:         the number of threshold samples (default = 200)
%
%   - thrs:         the vector of sampled thresholds
%   - fars:         the false accept rates at the sampled thresholds
%   - frrs:         the false reject rates at the sampled thresholds
%
% [ Description ]
%   - [thrs, fars, frrs] = slverifyroc(scores, rlabels, qlabels, op)
%     computes the verification ROC based on the pairwise scores between
%     the labeled refereneces and queries. 
%
%     Suppose there are nr references and nq queries, then scores should
%     be an nq x nr matrix, and rlabels and qlabels should be vectors of
%     length nq and nr respectively.
%
%     In the output, the quantized ROC is returned in form of three
%     vectors, the samples thresholds thrs, the false accept rates fars,
%     and the false reject rates frrs. By default, 200 thresholds are
%     uniformly sampled between the minimum score value and the maximum.
%
%   - [thrs, fars, frrs] = slverifyroc(scores, rlabels, qlabels, op, npts)
%     You can specify the number of threshold samples via npts.
%     Please note that npts should not be less than 3.
%
% [ History ]
%   - Created by Dahua Lin on Jun 10th, 2005
%   - Modified by Dahua Lin on May 1st, 2006
%   - Modified by Dahua Lin on Aug 8th, 2006
%       - add one more argument npts to tune the density of sampling
%   - Modified by Dahua Lin, on Jul 19, 2007
%       - base on new slroc function.
% 

%% parse and verify input arguments

error(nargchk(4, 5, nargin));

assert(isnumeric(scores) && ndims(scores) == 2, 'sltoolbox:slverifyroc:invalidarg', ...
    'The scores should be a 2D numeric matrix.');

assert(isnumeric(rlabels) && isvector(rlabels), 'sltoolbox:slverifyroc:invalidarg', ...
    'The rlabels should be a numeric vector.');
assert(isnumeric(qlabels) && isvector(qlabels), 'sltoolbox:slverifyroc:invalidarg', ...
    'The qlabels should be a numeric vector.');

[nr, nq] = size(scores);
assert(length(rlabels) == nr && length(qlabels) == nq, 'sltoolbox:slverifyroc:sizmismatch', ...
    'The size of scores do not match the numbers of labels.');

assert(ischar(op) && (strcmpi(op, 'high') || strcmpi(op, 'low')), ...
    'sltoolbox:slverifyroc:invalidarg', 'op should be either ''high'' or ''low''.');

if nargin < 5
    npts = 200;
else
    assert(isnumeric(npts) && isscalar(npts) && npts >= 3 && npts == fix(npts), ...
        'sltoolbox:slverifyroc:invalidarg', 'npts should be a positive integer not less than 3.');
end


%% main

% generate ground truth map

if size(rlabels, 2) > 1
    rlabels = reshape(rlabels, [nr 1]);
end
if size(qlabels, 1) > 1
    qlabels = reshape(qlabels, [1 nq]);
end

gt = bsxfun(@eq, rlabels, qlabels);

% generate threshold samples

minv = min(min(scores));
maxv = max(max(scores));

thrs = linspace(minv, maxv, npts);

% compute roc

[fars, frrs] = slroc(scores, gt, thrs, op);

